/*
 ******************************* Copyright (c)*********************************\
 **
 **                 (c) Copyright 2015, 蒋朋, china, qd. sd
 **                          All Rights Reserved
 **
 **                           By()
 **
 **
 **-----------------------------------版本信息------------------------------------
 ** 版    本: V0.1
 **
 **------------------------------------------------------------------------------
 ********************************End of Head************************************\
 */

package com.ewanghuiju.app.util;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.widget.Toast;

import com.ewanghuiju.app.R;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.permissions.PermissionChecker;
import com.luck.picture.lib.tools.BitmapUtils;
import com.luck.picture.lib.tools.DateUtils;
import com.luck.picture.lib.tools.PictureFileUtils;
import com.luck.picture.lib.tools.SdkVersionUtils;
import com.luck.picture.lib.tools.ValueOf;
import com.muddzdev.styleabletoast.StyleableToast;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

/**
 * 文 件 名: ImageUtil
 * 创 建 人: 蒋朋
 * 创建日期: 16-8-22 11:36
 * 描    述:
 * 修 改 人:
 * 修改时间：
 * 修改备注：
 */

public class ImageUtil {
    /**
     * 根据Uri获取图片绝对路径，解决Android4.4以上版本Uri转换
     *
     * @param context
     * @param imageUri
     */
    @TargetApi(19)
    public static String getImageAbsolutePath(Context context, Uri imageUri) {
        if (context == null || imageUri == null)
            return null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, imageUri)) {
            if (isExternalStorageDocument(imageUri)) {
                String docId = DocumentsContract.getDocumentId(imageUri);
                String[] split = docId.split(":");
                String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            } else if (isDownloadsDocument(imageUri)) {
                String id = DocumentsContract.getDocumentId(imageUri);
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            } else if (isMediaDocument(imageUri)) {
                String docId = DocumentsContract.getDocumentId(imageUri);
                String[] split = docId.split(":");
                String type = split[0];
                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                String selection = MediaStore.Images.Media._ID + "=?";
                String[] selectionArgs = new String[]{split[1]};
                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        } // MediaStore (and general)
        else if ("content".equalsIgnoreCase(imageUri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(imageUri))
                return imageUri.getLastPathSegment();
            return getDataColumn(context, imageUri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(imageUri.getScheme())) {
            return imageUri.getPath();
        }
        return null;
    }

    public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        String column = MediaStore.Images.Media.DATA;
        String[] projection = {column};
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

//    public void saveNetImage(String downloadPath){
//        PictureExternalPreviewActivity.LoadDataThread mLoadDataThread = new PictureExternalPreviewActivity.LoadDataThread(downloadPath);
//        mLoadDataThread.start();
//    }

    // 下载图片保存至手机
//    public void showLoadingImage(String urlPath) {
//        BufferedOutputStream bout = null;
//        Uri outImageUri = null;
//        try {
//            URL u = new URL(urlPath);
//            String path;
//            if (isAndroidQ) {
//                outImageUri = createOutImageUri();
//                if (outImageUri == null) {
//                    mHandler.sendEmptyMessage(SAVE_IMAGE_ERROR);
//                    return;
//                }
//                bout = new BufferedOutputStream(getContentResolver().openOutputStream(outImageUri));
//                path = PictureFileUtils.getPath(this, outImageUri);
//            } else {
//                String suffix = PictureMimeType.getLastImgSuffix(mMimeType);
//                String state = Environment.getExternalStorageState();
//                File rootDir =
//                        state.equals(Environment.MEDIA_MOUNTED)
//                                ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
//                                : getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
//                if (rootDir != null && !rootDir.exists() && rootDir.mkdirs()) {
//                }
//                File folderDir = new File(!state.equals(Environment.MEDIA_MOUNTED)
//                        ? rootDir.getAbsolutePath() : rootDir.getAbsolutePath() + File.separator + "Camera" + File.separator);
//                if (folderDir != null && !folderDir.exists() && folderDir.mkdirs()) {
//                }
//                String fileName = DateUtils.getCreateFileName("IMG_") + suffix;
//                File file = new File(folderDir, fileName);
//                path = file.getAbsolutePath();
//                bout = new BufferedOutputStream(new FileOutputStream(path));
//            }
//            if (bout == null) {
//                mHandler.sendEmptyMessage(SAVE_IMAGE_ERROR);
//                return;
//            }
//            byte[] buffer = new byte[1024 * 8];
//            int read;
//            int ava = 0;
//            long start = System.currentTimeMillis();
//            BufferedInputStream bin = new BufferedInputStream(u.openStream());
//            while ((read = bin.read(buffer)) > -1) {
//                bout.write(buffer, 0, read);
//                ava += read;
//                long speed = ava / (System.currentTimeMillis() - start);
//            }
//            bout.flush();
//            Message message = mHandler.obtainMessage();
//            message.what = SAVE_IMAGE_SUCCESSFUL;
//            message.obj = path;
//            mHandler.sendMessage(message);
//        } catch (IOException e) {
//            mHandler.sendEmptyMessage(SAVE_IMAGE_ERROR);
//            if (outImageUri != null) {
//                getContentResolver().delete(outImageUri, null, null);
//            }
//            e.printStackTrace();
//        } finally {
//            try {
//                if (bout != null) {
//                    bout.close();
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }

    public static void saveImageToLocal(Activity mActivity, String path) {
        if (PermissionChecker.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//            downloadPath = path;
            String currentMimeType = PictureMimeType.getImageMimeType(path);
            String mMimeType = PictureMimeType.isJPG(currentMimeType) ? PictureMimeType.MIME_TYPE_JPEG : currentMimeType;
            try {
                if (SdkVersionUtils.checkedAndroid_Q()) {
                    savePictureAlbumAndroidQ(mActivity, path.startsWith("content://") ? Uri.parse(path) : Uri.fromFile(new File(path)), mMimeType);
                } else {
                    // 把文件插入到系统图库
                    savePictureAlbum(mActivity, path, mMimeType);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            PermissionChecker.requestPermissions(mActivity,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PictureConfig.APPLY_STORAGE_PERMISSIONS_CODE);
        }
    }

    /**
     * 保存相片至本地相册
     *
     * @throws Exception
     */
    private static void savePictureAlbum(Activity mActivity, String path, String mMimeType) throws Exception {
        String suffix = PictureMimeType.getLastImgSuffix(mMimeType);
        String state = Environment.getExternalStorageState();
        File rootDir = state.equals(Environment.MEDIA_MOUNTED)
                ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
                : mActivity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (rootDir != null && !rootDir.exists() && rootDir.mkdirs()) {
        }
        File folderDir = new File(SdkVersionUtils.checkedAndroid_Q() || !state.equals(Environment.MEDIA_MOUNTED)
                ? rootDir.getAbsolutePath() : rootDir.getAbsolutePath() + File.separator + "Camera" + File.separator);
        if (folderDir != null && !folderDir.exists() && folderDir.mkdirs()) {
        }
        String fileName = DateUtils.getCreateFileName("IMG_") + suffix;
        File file = new File(folderDir, fileName);
        PictureFileUtils.copyFile(path, file.getAbsolutePath());

        StyleableToast.makeText(mActivity, "保存成功", Toast.LENGTH_SHORT, R.style.mytoast).show();
//        Message message = mHandler.obtainMessage();
//        message.what = SAVE_IMAGE_SUCCESSFUL;
//        message.obj = file.getAbsolutePath();
//        mHandler.sendMessage(message);

    }

    /**
     * 保存图片到picture 目录，Android Q适配，最简单的做法就是保存到公共目录，不用SAF存储
     *
     * @param inputUri
     */
    private static void savePictureAlbumAndroidQ(Activity mActivity, Uri inputUri, String mMimeType) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, DateUtils.getCreateFileName("IMG_"));
        contentValues.put(MediaStore.Images.Media.DATE_TAKEN, ValueOf.toString(System.currentTimeMillis()));
        contentValues.put(MediaStore.Images.Media.MIME_TYPE, mMimeType);
//        contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, PictureMimeType.DCIM);
        Uri uri = mActivity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        if (uri == null) {
//            mHandler.sendEmptyMessage(SAVE_IMAGE_ERROR);
            StyleableToast.makeText(mActivity, "保存失败", Toast.LENGTH_SHORT, R.style.mytoast).show();
            return;
        }
        AsyncTask.SERIAL_EXECUTOR.execute(() -> {
            OutputStream outputStream = null;
            ParcelFileDescriptor parcelFileDescriptor = null;
            try {
                outputStream = mActivity.getContentResolver().openOutputStream(uri);
                parcelFileDescriptor = mActivity.getContentResolver().openFileDescriptor(inputUri, "r");
                BitmapFactory.Options opts = new BitmapFactory.Options();
                opts.inJustDecodeBounds = true;
                opts.inSampleSize = 2;
                opts.inJustDecodeBounds = false;
                Bitmap bitmap = BitmapFactory.decodeFileDescriptor(parcelFileDescriptor.getFileDescriptor(), null, opts);
                if (bitmap != null) {
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N && PictureMimeType.isJPEG(mMimeType)) {
                        ExifInterface exifInterface = new ExifInterface(parcelFileDescriptor.getFileDescriptor());
                        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
                        int rotationAngle = BitmapUtils.getRotationAngle(orientation);
                        bitmap = BitmapUtils.rotatingImage(bitmap, rotationAngle);
                    }
                    if (bitmap != null) {
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                        outputStream.close();
                        String path = PictureFileUtils.getPath(mActivity, uri);
                        StyleableToast.makeText(mActivity, "保存成功", Toast.LENGTH_SHORT, R.style.mytoast).show();
//                        Message message = mHandler.obtainMessage();
//                        message.what = SAVE_IMAGE_SUCCESSFUL;
//                        message.obj = path;
//                        mHandler.sendMessage(message);
                        bitmap.recycle();
                    }
                } else {
//                    mHandler.sendEmptyMessage(SAVE_IMAGE_ERROR);
                    StyleableToast.makeText(mActivity, "保存失败", Toast.LENGTH_SHORT, R.style.mytoast).show();
                }
            } catch (Exception e) {
//                mHandler.sendEmptyMessage(SAVE_IMAGE_ERROR);
                StyleableToast.makeText(mActivity, "保存失败", Toast.LENGTH_SHORT, R.style.mytoast).show();
                e.printStackTrace();
            } finally {
                PictureFileUtils.close(parcelFileDescriptor);
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Return the compressed bitmap using sample size.
     *
     * @param src        The source of bitmap.
     * @param sampleSize The sample size.
     * @param recycle    True to recycle the source of bitmap, false otherwise.
     * @return the compressed bitmap
     */
    public static Bitmap compressBySampleSize(final Bitmap src,
                                              final int sampleSize,
                                              final boolean recycle) {
        if (isEmptyBitmap(src)) return null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = sampleSize;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bytes = baos.toByteArray();
        if (recycle && !src.isRecycled()) src.recycle();
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    }

    private static boolean isEmptyBitmap(final Bitmap src) {
        return src == null || src.getWidth() == 0 || src.getHeight() == 0;
    }


    /**
     * Return the compressed data using quality.
     *
     * @param src         The source of bitmap.
     * @param maxByteSize The maximum size of byte.
     * @return the compressed data using quality
     */
    public static byte[] compressByQuality(final Bitmap src, final long maxByteSize) {
        return compressByQuality(src, maxByteSize, false);
    }

    /**
     * Return the compressed data using quality.
     *
     * @param src         The source of bitmap.
     * @param maxByteSize The maximum size of byte.
     * @param recycle     True to recycle the source of bitmap, false otherwise.
     * @return the compressed data using quality
     */
    public static byte[] compressByQuality(final Bitmap src,
                                           final long maxByteSize,
                                           final boolean recycle) {
        if (isEmptyBitmap(src) || maxByteSize <= 0) return new byte[0];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bytes;
        if (baos.size() <= maxByteSize) {
            bytes = baos.toByteArray();
        } else {
            baos.reset();
            src.compress(Bitmap.CompressFormat.JPEG, 0, baos);
            if (baos.size() >= maxByteSize) {
                bytes = baos.toByteArray();
            } else {
                // find the best quality using binary search
                int st = 0;
                int end = 100;
                int mid = 0;
                while (st < end) {
                    mid = (st + end) / 2;
                    baos.reset();
                    src.compress(Bitmap.CompressFormat.JPEG, mid, baos);
                    int len = baos.size();
                    if (len == maxByteSize) {
                        break;
                    } else if (len > maxByteSize) {
                        end = mid - 1;
                    } else {
                        st = mid + 1;
                    }
                }
                if (end == mid - 1) {
                    baos.reset();
                    src.compress(Bitmap.CompressFormat.JPEG, st, baos);
                }
                bytes = baos.toByteArray();
            }
        }
        if (recycle && !src.isRecycled()) src.recycle();
        return bytes;
    }


    /**
     * Bytes to bitmap.
     *
     * @param bytes The bytes.
     * @return bitmap
     */
    public static Bitmap bytes2Bitmap(final byte[] bytes) {
        return (bytes == null || bytes.length == 0)
                ? null
                : BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }

}
